import React, { useState, useEffect, useRef } from 'react';
import { getIceServers, getRtmpUrl, getHttpFlvUrl, getHlsUrl, getHlsUrlOriginal, getHttpFlvUrlOriginal, getRtmpUrlOriginal } from './config';
import { connectWebRTC, stopWebRTC, getWebRTCStatus} from './services/RTCService';
import CameraCapture from './components/CameraCapture';
import VideoPlayer from './components/VideoPlayer';
import './styles/App.css';

// 视频约束
const VIDEO_CONSTRAINTS = {
  width: { ideal: 1280 },
  height: { ideal: 720 },
  frameRate: { ideal: 30 }
};

// 音频约束
const AUDIO_CONSTRAINTS = true;

const App = () => {
  const [isStreaming, setIsStreaming] = useState(false);
  const [status, setStatus] = useState('waiting');
  const [errorMessage, setErrorMessage] = useState('');
  const [cameraAvailable, setCameraAvailable] = useState(true);
  const [isTryingAgain, setIsTryingAgain] = useState(false);
  const cameraRef = useRef(null);
  const mediaStreamRef = useRef(null);
  const retryTimeoutRef = useRef(null);

  // 检查摄像头是否可用
  const checkCameraAvailability = async () => {
    try {
      const devices = await navigator.mediaDevices.enumerateDevices();
      const videoDevices = devices.filter(device => device.kind === 'videoinput');
      
      if (videoDevices.length === 0) {
        console.warn('未检测到摄像头设备');
        setCameraAvailable(false);
        setErrorMessage('未检测到摄像头设备，请确认摄像头已连接并授予权限');
        return false;
      }
      
      console.log('检测到以下摄像头设备:', videoDevices);
      setCameraAvailable(true);
      return true;
    } catch (error) {
      console.error('检查摄像头设备时出错:', error);
      setCameraAvailable(false);
      setErrorMessage(`检查摄像头设备时出错: ${error.message}`);
      return false;
    }
  };

  useEffect(() => {
    // 组件挂载时检查摄像头
    checkCameraAvailability();
    
    // 组件卸载时清理资源
    return () => {
      if (mediaStreamRef.current) {
        mediaStreamRef.current.getTracks().forEach(track => track.stop());
      }
      if (retryTimeoutRef.current) {
        clearTimeout(retryTimeoutRef.current);
      }
    };
  }, []);

  useEffect(() => {
    // 注册WebRTC状态回调
    getWebRTCStatus(handleWebRTCStatus);
    
    return () => {
      // 清除回调
      getWebRTCStatus(null);
    };
  }, []);

  const handleWebRTCStatus = (statusData) => {
    console.log('WebRTC状态:', statusData);
    
    if (statusData.status === 'ice') {
      if (statusData.state === 'checking') {
        setStatus('connecting');
      } else if (statusData.state === 'connected' || statusData.state === 'completed') {
        setStatus('streaming');
      } else if (statusData.state === 'failed' || statusData.state === 'disconnected' || statusData.state === 'closed') {
        setStatus('error');
        setErrorMessage('WebRTC连接失败，请检查网络连接');
        
        // 超时自动重试
        if (statusData.reason === 'timeout' && !isTryingAgain) {
          console.log('ICE连接超时，将自动重试...');
          setIsTryingAgain(true);
          
          // 停止当前连接然后重试
          stopStreaming().then(() => {
            setTimeout(() => {
              startStreaming().then(() => {
                setIsTryingAgain(false);
              }).catch(err => {
                console.error('重试失败:', err);
                setIsTryingAgain(false);
              });
            }, 2000);
          });
        }
      }
    }
  };

  const startStreaming = async () => {
    try {
      setStatus('正在启动...');
      setErrorMessage('');
      setIsTryingAgain(false);
      
      // 先检查摄像头是否可用
      const isCameraAvailable = await checkCameraAvailability();
      if (!isCameraAvailable) {
        throw new Error('摄像头不可用，请确认摄像头已连接并授予权限');
      }
      
      console.log('准备获取摄像头权限...');
      
      // 获取摄像头媒体流
      const stream = await navigator.mediaDevices.getUserMedia({ 
        video: VIDEO_CONSTRAINTS, 
        audio: AUDIO_CONSTRAINTS 
      });
      
      console.log('成功获取摄像头流:', stream.id);
      mediaStreamRef.current = stream;
      
      // 设置本地视频预览
      if (cameraRef.current) {
        console.log('设置视频预览...');
        cameraRef.current.srcObject = stream;
      } else {
        console.error('cameraRef.current 不存在');
      }
      
      // 开始WebRTC推流
      console.log('准备开始WebRTC推流...');
      setStatus('connecting');
      
      try {
        await connectWebRTC(stream);
        
        setIsStreaming(true);
        setStatus('streaming');
        console.log('成功开始WebRTC推流');
      } catch (rtcError) {
        console.error('WebRTC连接失败:', rtcError);
        
        // 显示更具体的错误信息
        let errorMsg = '';
        if (rtcError.message.includes('SRS错误')) {
          errorMsg = `服务器错误: ${rtcError.message}`;
        } else if (rtcError.message.includes('SRS服务器响应错误')) {
          errorMsg = `连接失败: ${rtcError.message}`;
        } else {
          errorMsg = `推流失败: ${rtcError.message}`;
        }
        
        setErrorMessage(errorMsg);
        setStatus('error');
        
        // 对于特定错误进行重试
        if (rtcError.message.includes('404') || rtcError.message.includes('timeout')) {
          console.log('服务器连接问题，2秒后自动重试...');
          setIsTryingAgain(true);
          
          retryTimeoutRef.current = setTimeout(async () => {
            try {
              await connectWebRTC(stream);
              setIsStreaming(true);
              setStatus('streaming');
              setIsTryingAgain(false);
            } catch (retryError) {
              console.error('重试失败:', retryError);
              setIsTryingAgain(false);
              setStatus('error');
              setErrorMessage('重试失败，请检查网络连接或刷新页面');
            }
          }, 2000);
        }
      }
      
    } catch (error) {
      console.error('获取摄像头或开始推流失败:', error);
      setStatus('error');
      setErrorMessage(typeof error === 'string' ? error : error.message || '未知错误');
      
      // 不要立即释放摄像头资源，因为可能需要重试
      // 只有在特定错误（非网络相关）时才释放资源
      if (error.name === 'NotAllowedError' || error.name === 'NotFoundError' || 
          error.message.includes('摄像头不可用')) {
        if (mediaStreamRef.current) {
          mediaStreamRef.current.getTracks().forEach(track => track.stop());
          mediaStreamRef.current = null;
        }
      } else {
        // 对于其他错误，尝试在短暂延迟后自动重试一次
        setIsTryingAgain(true);
        setErrorMessage('正在尝试重新连接...');
        
        retryTimeoutRef.current = setTimeout(async () => {
          if (mediaStreamRef.current) {
            console.log('自动重试连接...');
            try {
              await connectWebRTC(mediaStreamRef.current);
              setIsStreaming(true);
              setStatus('streaming');
              setIsTryingAgain(false);
            } catch (retryError) {
              console.error('重试失败:', retryError);
              setIsTryingAgain(false);
              setStatus('error');
              setErrorMessage('重试失败，请手动点击"重试"按钮');
            }
          }
        }, 2000);
      }
    }
  };

  const stopStreaming = async () => {
    setStatus('stopping');
    
    try {
      // 停止WebRTC推流
      await stopWebRTC();
      
      // 停止所有媒体轨道
      if (mediaStreamRef.current) {
        mediaStreamRef.current.getTracks().forEach(track => track.stop());
        mediaStreamRef.current = null;
      }
      
      // 清除视频源
      if (cameraRef.current) {
        cameraRef.current.srcObject = null;
      }
      
      // 清除任何重试定时器
      if (retryTimeoutRef.current) {
        clearTimeout(retryTimeoutRef.current);
        retryTimeoutRef.current = null;
      }
      
      // 添加强制状态更新 - 确保状态被正确设置
      console.log('强制设置推流状态为已停止');
      setIsStreaming(false);
      setStatus('stopped');
      setIsTryingAgain(false);
      
      // 通知其他组件状态已更改
      if (typeof handleStreamStatusChange === 'function') {
        handleStreamStatusChange(false);
      }
    } catch (error) {
      console.error('停止推流失败:', error);
      setErrorMessage(`停止推流失败: ${error.message}`);
      setStatus('error');
      
      // 即使出错也要将推流状态设为false
      setIsStreaming(false);
    }
  };

  // 获取状态文本
  const getStatusText = () => {
    switch (status) {
      case 'waiting':
        return '等待开始...';
      case 'loading':
        return '正在启动摄像头...';
      case 'streaming':
        return '正在推流中...';
      case 'stopping':
        return '正在停止...';
      case 'stopped':
        return '已停止';
      case 'error':
        return `错误: ${errorMessage || '未知错误'}`;
      case 'reconnecting':
        return '正在重新连接...';
      default:
        return '未知状态';
    }
  };

  // 处理流状态变化 - 确保状态同步
  const handleStreamStatusChange = (streaming) => {
    console.log('流状态变化:', streaming);
    setIsStreaming(streaming);
    
    // 确保status和isStreaming保持同步
    if (streaming) {
      setStatus('streaming');
    } else {
      // 如果streaming为false，则将status设为waiting（准备就绪状态）
      setStatus('waiting');
    }
  };
  
  // 处理摄像头状态变化
  const handleCameraStatusChange = (isLoading) => {
    setStatus(isLoading ? 'loading' : (isStreaming ? 'streaming' : 'waiting'));
  };
  
  // 获取HTTP-FLV地址
  const getFlvUrl = () => {
    return getHttpFlvUrl();
  };

  return (
    <div className="container container-flex">
      <h1 className="app-title">面部检测 SRS WebRTC 推流系统</h1>
      
      {/* 状态展示 */}
      <div className={`status ${status}`}>
        <strong>推流状态: </strong>{getStatusText()}
        {process.env.NODE_ENV !== 'production' && (
          <span style={{fontSize: '10px', marginLeft: '10px', color: '#666'}}>
            (isStreaming: {isStreaming ? 'true' : 'false'}, status: {status})
          </span>
        )}
      </div>
      
      {/* 视频容器 */}
      <div className="stream-container" style={{
        display: 'flex',
        gap: '20px',
        marginTop: '20px'
      }}>
        {/* 左侧推流区域 */}
        <div className="camera-section" style={{ 
          flex: '1',
          minWidth: '400px',
          display: 'flex',
          flexDirection: 'column',  // 确保内容垂直排列
          border: '1px solid #eee',
          borderRadius: '8px',
          overflow: 'hidden'
        }}>
          <div className="section-header" style={{ 
            padding: '10px',
            backgroundColor: '#f8f9fa',
            borderBottom: '1px solid #eee'
          }}>
            <h2 style={{ margin: '0' }}>WebRTC 推流</h2>
          </div>
          
          {/* 确保高度足够且不使用overflow:hidden */}
          <div style={{ 
            height: '450px',  // 增加高度
            backgroundColor: '#000',
            position: 'relative',
            display: 'flex',
            flexDirection: 'column'
          }}>
            <CameraCapture 
              onStreamStatusChange={handleStreamStatusChange}
              onCameraStatusChange={handleCameraStatusChange}
              ref={cameraRef} 
            />
          </div>
          <div className="section-footer" style={{ padding: '10px', fontSize: '14px' }}>
            <p>点击"开始推流"按钮，将摄像头视频通过WebRTC推送到SRS服务器</p>
          </div>
        </div>
        
        {/* 右侧播放区域 */}
        <div className="player-section" style={{ 
          flex: '1',
          minWidth: '400px',
          border: '1px solid #eee',
          borderRadius: '8px',
          overflow: 'hidden'
        }}>
          <div className="section-header" style={{ 
            padding: '10px',
            backgroundColor: '#f8f9fa',
            borderBottom: '1px solid #eee'
          }}>
            <h2 style={{ margin: '0' }}>HTTP-FLV 播放</h2>
          </div>
          <div style={{ height: '400px', backgroundColor: '#000', position: 'relative' }}>
            <VideoPlayer url={getFlvUrl()} isStreaming={isStreaming} />
          </div>
          {isStreaming && (
            <div className="section-footer" style={{ padding: '10px', fontSize: '14px' }} >
              <p>HTTP-FLV 播放地址: <code>{getHttpFlvUrl()}</code></p>
              <p>RTMP 播放地址: <code>{getRtmpUrl()}</code></p>
            <p>HLS 播放地址: <code>{getHlsUrl()}</code></p>
            <p>HTTP-FLV 直接地址: <code>{getHttpFlvUrlOriginal()}</code></p>
            <p>RTMP 直接地址: <code>{getRtmpUrlOriginal()}</code></p>
              <p>HLS 直接地址: <code>{getHlsUrlOriginal()}</code></p>
            </div>
          )}
        </div>
      </div>
      <div style={{flex: '1'}}></div>
      <div className="section-footer" style={{ padding: '10px', fontSize: '14px' }} >
        <p>
          <strong>注意:</strong>
          <br />
          推流地址和播放地址是不同的，推流地址是推流到SRS服务器的地址，播放地址是播放SRS服务器的地址。
          <br />
        </p>
        {/* 作者 */}
        <p>
          <strong>DDCoder 开发</strong>
        </p>
      </div>
    </div>
  );
};

export default App; 